﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace FrameBuilderLib
{
    [Serializable]
    public class HTML
    {
        public Head head { set; get; }
        public Body body { set; get; }
       
        /// <summary>
        /// процедура для разбивки сайта на фреймы
        /// </summary>
        /// <param name="content">на вход - список, где все теги в отдельных строках</param>
        public HTML(string text)
        {
            List<string> content = text.Split('\n', '\r').ToList<string>();
            content = (from c in content where c != "" select c).ToList<string>();
            Body _body=null;
            Head _head=null;
            int num=0;
            if (content[num++].ToLower().Trim() == "<html>" && num<=content.Count)
            {
                _head = new Head(content,ref num);
                _body = new Body(content,ref num);
            }
            if (content[num++].ToLower().Trim() == "</html>" && num <= content.Count)
            {
                body = _body;
                head = _head;
            }
        }

        public HTML() { }

        public bool Find(List<List<string>> wordlist)
        {
            bool find = false;
            if (head!=null) find = head.Find(wordlist);
            if (!find && (body!=null)) 
                find = body.Find(wordlist);
            return find;
        }

        public string HTML_ToString()
        {
            string res = "";
            
            foreach (Title t in head.titles)
            {
                res += t.text+" ";
            }
            res += "\n";
            foreach (Header h in body.headers)
            {
                res += h.text+" ";
            }
            res += "\n";
            foreach (Paragraph p in body.paragraphs)
            {
                res += p.text;
                res += "\n";
            }


            return res;
        }

        public void Serialize(string path)
        {
            if (File.Exists(path))
            {
                File.Delete(path);
            }
            XmlSerializer XmlSer = new XmlSerializer(typeof(HTML));
            FileStream stream = new FileStream(path, FileMode.OpenOrCreate);
            XmlSer.Serialize(stream, this);
            stream.Close();
        }
        
    }

    [Serializable]
    public class Body
    {
        public List<Paragraph> paragraphs { set; get; }
        public List<Header> headers { set; get; }

        public Body() { }

        public Body(List<string> content,ref int num)
        {
            List<Paragraph> _paragraphs = new List<Paragraph>();
            List<Header> _headers = new List<Header>();
            if (content[num++].ToLower().Trim() == "<body>" && num <= content.Count)
            {
                while (content[num].ToLower().Trim() != "</body>" && num < content.Count)
                {
                    switch (content[num].ToLower().Trim())
                    {
                        case "<p>":
                            _paragraphs.Add(new Paragraph(content,ref num));
                            break;
                        case "<h1>": case "<h2>":  case "<h3>": case "<h4>": case "<h5>": case"<h6>":
                            _headers.Add(new Header(content, ref num));
                            break;
                    }
                }
            }
            if (content[num++].ToLower().Trim() == "</body>" && num <= content.Count)
            {
                paragraphs = _paragraphs;
                headers = _headers;
            }
        }

        public bool Find(List<List<string>> wordlist)
        {
            bool find = false;
            if (headers.Count > 0)
            {
                int i = 0;
                while (!find && headers.Count > i)
                {
                    find = headers[i++].Find(wordlist);
                }
            }
            if (!find && paragraphs.Count > 0)
            {
                int i = 0;
                while (!find && paragraphs.Count > i)
                {
                    find = paragraphs[i++].Find(wordlist);
                }
            }
            return find;
        }
    }

    [Serializable]
    public class Paragraph
    {
        public String text { set; get; }

        public Paragraph() { }

        public Paragraph(List<string> content, ref int num)
        {
            string _text = null;
            if (content[num++].ToLower().Trim() == "<p>" && num <= content.Count)
            {
                _text = content[num++];
            }
            while (content[num].ToLower().Trim() != "</p>" && num < content.Count)
            {
                _text += " " + content[num++];
            }
            if (content[num++].ToLower().Trim() == "</p>" && num <= content.Count)
            {
                text = _text;
            }
            text = LemmAnylser.GetText(text);
        }

        public bool Find(List<List<string>> wordlist)
        {
            return LemmAnylser.FindWordInText(wordlist, text);
        }
    }

    [Serializable]
    public class Header
    {
        public String text { set; get; }

        public Header() { }

        public Header(List<string> content, ref int num)
        {
            string _text = null;
            string[] begin_tags = { "<h1>", "<h2>", "<h3>", "<h4>", "<h5>", "<h6>" };
            string[] end_tags = { "</h1>", "</h2>", "</h3>", "</h4>", "</h5>", "</h6>" };
            if (begin_tags.Contains(content[num++].ToLower().Trim()) && num <= content.Count)
            {
                _text = content[num++];
            }
            while (!end_tags.Contains(content[num].ToLower().Trim()) && num < content.Count)
                _text +=" "+ content[num++];
            if (end_tags.Contains(content[num++].ToLower().Trim()) && num <= content.Count)
            {
                text = _text;
            }
            text = LemmAnylser.GetText(text);
        }

        public bool Find(List<List<string>> wordlist)
        {
            return LemmAnylser.FindWordInText(wordlist, text);
        }
    }

    [Serializable]
    public class Head
    {
        //head может не быть, а может состоять из 1 или неск-х Title 
        public List<Title> titles { set; get; }

        public Head() { }

        public Head(List<string> content, ref int num)
        {
            List<Title> _titles = new List<Title>();
            if (content[num++].ToLower().Trim() == "<head>" && num <= content.Count)
            {
                while (content[num].ToLower().Trim() == "<title>" && num < content.Count)
                {
                    _titles.Add(new Title(content, ref num));
                }
            }
            if (content[num++].ToLower().Trim() == "</head>" && num <= content.Count)
            {
                titles = _titles;
            }
        }

        public bool Find(List<List<string>> wordlist)
        {
            bool find = false;
            if (titles.Count > 0)
            {
                int i=0;
                while (!find && titles.Count > i)
                {
                    find = titles[i++].Find(wordlist);
                }
            }
            return find;
        }
    }

    [Serializable]
    public class Title
    {
        public String text { set; get; }

        public Title() { }

        public Title(List<string> content, ref int num)
        {
            string _text = null;
            if (content[num++].ToLower().Trim() == "<title>" && num <= content.Count)
            {
                _text = " "+content[num++];
            }
            while (content[num].ToLower().Trim() != "</title>" && num < content.Count)
                _text += content[num++];
            if (content[num++].ToLower().Trim() == "</title>" && num <= content.Count)
            {
                text = _text;
            }
            
            text=LemmAnylser.GetText(text);
        }

        public bool Find(List<List<string>> wordlist)
        {
            return LemmAnylser.FindWordInText(wordlist, text);
        }
    }
}
